java锁升级简述

您所在的位置:网站首页 java 锁升级 java锁升级简述

java锁升级简述

2023-08-23 05:26| 来源: 网络整理| 查看: 265

java锁升级简述 概念图流程简述CASjava对象的内存布局对象头分为两部分:java对象在内存中布局分为三块区域: 池化思想Monitors(管程)可重入设计monitorentermonitorexit为什么会有两个monitorexit ? 偏向锁获取偏向锁的三个条件:偏向锁优势缺点偏向锁是否一定高效率? 轻量级锁(自旋锁)轻量级锁优势缺点 重量级锁优势缺点 用户空间锁vs重量级锁本文部分图片来自https://www.bilibili.com/video/BV1vA411t7yd

概念图

在这里插入图片描述

流程简述

java 创建出来对象以后先是普通对象,此时没有任何锁,之后需要加锁的时候会先为其添加偏向锁,当竞争激烈一些的时候,会为其添加轻量级锁,如果竞争更加激烈了,会为其添加重量级锁。

CAS

在这里插入图片描述 先考虑这样一种情况,当前线程要对内存中的一个值进行修改:比如有一个变量x=0,要对其进行加一操作,线程一般如此操作,先进行读取,进行加一,x1=1,比较此时内存中x的是否为0,如果为0,进行写入x=1,否则重新读取。重新读取,就发生在多个线程同时对x进行修改的情况下。 (至于ABA的问题则是,对x进行写入的时候,验证到x=0,但是我们不知道,这个x是否经历过类似于0->1->0这样的过程)

java对象的内存布局

在这里插入图片描述 借助工具:openjdk 我们可以查看到对象在内存中的布局情况。 在这里插入图片描述 在64bit JVM中:

对象头分为两部分:

1)Mark Word 2)Class Pointer

java对象在内存中布局分为三块区域:

1)对象头 :固定12字节 2)实例数据:不固定 3)数据对齐:填充数据,保证字节数为8的整数倍

池化思想

以线程池为例子,我们不可能为每一个线程都分配到资源,就需要引入池化的思想。 比如:现在允许最大线程数是5个,0时,必须同一个线程访问,才能拿到锁,也就意味着线程访问临界资源时必须互斥

monitorexit

指向同步代码块退出的位置的指针,释放锁过程就是将计数器减一,同时判断count是否为0,如果为0,那么就设置锁标记为释放状态,然后调用object的notify方法,唤起其他将要获取锁的线程。

为什么会有两个monitorexit ?

第二个monitorexit 是为了防止,第一个释放过程中出现异常,以确保必定释放。

偏向锁 获取偏向锁的三个条件:

1)JVM开启了偏向锁 2)判断锁状态是01 3)当前线程是否等于Mark Word里面存储的Thread ID

偏向锁优势

在于消耗很少的资源去获取锁

缺点

释放锁消耗的资源会比较大

偏向锁是否一定高效率?

不一定 在明确知道多个线程强烈竞争的时候,系统会把资源大量消耗在撤销上。

轻量级锁(自旋锁)

在线程的竞争比较多的情况下会升级到轻量级锁 每个线程在线程栈中生成LockRecord,用CAS方式尝试把自己的指针更新到markword 每一次锁重入,都会有一个LockRecord

轻量级锁优势

竞争比较多情况下,竞争的线程不会阻塞(存在自旋情况),提高程序并发能力

缺点

获取不到锁时,会不停自旋,会大量消好CPU性能

重量级锁

竞争非常激烈时,会升级到重量级锁,它不是自旋,而是获取不到锁的线程全部陷入等待 自旋是要占用CPU的,线程数量过多的时候用自旋不合适 (OLD)10次,PreSpinLock ,cpu/2 Adaptive CAS

优势

等待线程会消耗很少的CPU

缺点

并发性较低

用户空间锁vs重量级锁

偏向锁,自旋锁都是用户空间完成 重量级锁是需要向内核申请

本文部分图片来自https://www.bilibili.com/video/BV1vA411t7yd


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3